home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 5 / Amiga Plus Sonderheft 1996 #5.iso / programme / picturedt_v43 / demo / pbm / readpbm.c < prev   
C/C++ Source or Header  |  1986-04-25  |  16KB  |  789 lines

  1. /*
  2.  
  3.     V43 ppm.datatype
  4.  
  5.     (c) 1995-1996 by Matthias Scheler <tron@lyssa.owl.de>
  6.  
  7. */
  8.  
  9. #include "PBM.h"
  10.  
  11. #include <exec/memory.h>
  12.  
  13. #include <proto/graphics.h>
  14. #include <proto/utility.h>
  15.  
  16. #include <string.h>
  17.  
  18. #define MIN(a,b) __builtin_min((a),(b))
  19.  
  20. #define IsWhiteSpace(c) (((c)==' ')||((c)=='\t')||((c)=='\r')||((c)=='\n'))
  21.  
  22. #define PBM_HEADER_SIZE 3L
  23.  
  24. #define GRAYSCALE_COLORS 256
  25.  
  26. LONG __regargs GetNum(struct FFRHandle *FH)
  27.  
  28. {
  29.  LONG In,Num;
  30.  
  31.  In=FFRGetC(FH);
  32.  while ((In=='#')||IsWhiteSpace(In))
  33.   {
  34.    if (In=='#')
  35.     {
  36.      In=FFRGetC(FH);
  37.      while ((In!='\r')&&(In!='\n'))
  38.       if (In==-1L) return -1L;
  39.       else In=FFRGetC(FH);
  40.     }
  41.  
  42.    In=FFRGetC(FH);
  43.   }
  44.  if (In==-1L) return -1L;
  45.  
  46.  if ((In<'0')||(In>'9')) return -1L;
  47.  Num=In-'0';
  48.  
  49.  In=FFRGetC(FH);
  50.  while ((In>='0')&&(In<='9'))
  51.   {
  52.    Num=Num*10L+In-'0';
  53.    In=FFRGetC(FH);
  54.   }
  55.  
  56.  while (In=='#')
  57.   {
  58.    In=FFRGetC(FH);
  59.    while ((In!='\r')&&(In!='\n'))
  60.     if (In==-1L) return -1L;
  61.     else In=FFRGetC(FH);
  62.  
  63.    In=FFRGetC(FH);
  64.   }
  65.  
  66.  return ((In==-1L)||IsWhiteSpace(In))?Num:-1L;
  67. }
  68.  
  69. ULONG __regargs RGB8to32(ULONG RGB)
  70.  
  71. {
  72.  return (RGB<<24)|(RGB<<16)|(RGB<<8)|RGB;
  73. }
  74.  
  75. void FreeAmigaBitMap(struct BitMap *BitMap)
  76.  
  77. {
  78.  ULONG Index;
  79.  
  80.  for (Index=0L; Index<BitMap->Depth; Index++)
  81.   FreeMem (BitMap->Planes[Index],BitMap->BytesPerRow*BitMap->Rows);
  82.  
  83.  FreeVec (BitMap);
  84. }
  85.  
  86. struct BitMap __regargs *AllocAmigaBitMap(LONG Width,LONG Depth)
  87.  
  88. {
  89.  struct BitMap *BitMap;
  90.  ULONG Index;
  91.  
  92.  if ((BitMap=AllocVec(sizeof(struct BitMap),MEMF_PUBLIC))==NULL) return NULL;
  93.  InitBitMap (BitMap,Depth,Width,1L);
  94.  
  95.  for (Index=0L; Index<Depth; Index++)
  96.   if ((BitMap->Planes[Index]=AllocMem(BitMap->BytesPerRow*BitMap->Rows,MEMF_CHIP|MEMF_CLEAR))==NULL)
  97.    {
  98.     BitMap->Depth=Index;
  99.     FreeAmigaBitMap (BitMap);
  100.     return NULL;
  101.   }
  102.  
  103.  return BitMap;
  104. }
  105.  
  106. /*
  107.  
  108.     P1 format: monochrom
  109.  
  110.     We use the old pre V43 interface to handle it.
  111.  
  112. */
  113.  
  114. LONG __regargs ReadPBM1(struct FFRHandle *FH,struct BitMapHeader *BMHD,
  115.                         Class *C,Object *O,struct TagItem *Attrs)
  116.  
  117. {
  118.  LONG Width,Height,Y,X,In,*CRegs;
  119.  struct BitMap *TempBitMap,*BitMap;
  120.  struct ColorRegister *CMAP;
  121.  UBYTE Mask;
  122.  ULONG ViewModes;
  123.  
  124.  if ((Width=GetNum(FH))<1L)
  125.   {
  126.    CloseFFR (FH);
  127.  
  128.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  129.    return FALSE;
  130.   }
  131.  if ((Height=GetNum(FH))<1L)
  132.   {
  133.    CloseFFR (FH);
  134.  
  135.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  136.    return FALSE;
  137.   }
  138.  
  139.  (void)SetDTAttrs(O,NULL,NULL,PDTA_NumColors,2L,TAG_DONE);
  140.  if (GetDTAttrs(O,PDTA_ColorRegisters,&CMAP,PDTA_CRegs,&CRegs,TAG_DONE)==2L)
  141.   {
  142.    CMAP->red=255;
  143.    CMAP->green=255;
  144.    CMAP->blue=255;
  145.    CMAP++;
  146.  
  147.    *CRegs++=0xFFFFFFFFL;
  148.    *CRegs++=0xFFFFFFFFL;
  149.    *CRegs++=0xFFFFFFFFL;
  150.  
  151.    CMAP->red=0;
  152.    CMAP->green=0;
  153.    CMAP->blue=0;
  154.    CMAP++;
  155.  
  156.    *CRegs++=0x00000000L;
  157.    *CRegs++=0x00000000L;
  158.    *CRegs=0x00000000L;
  159.   }
  160.  
  161.  if ((TempBitMap=AllocAmigaBitMap(Width,1L))==NULL)
  162.   {
  163.    CloseFFR (FH);
  164.  
  165.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  166.    return FALSE;
  167.   }
  168.  
  169.  if ((BitMap=AllocBitMap(Width,Height,1L,BMF_CLEAR|BMF_DISPLAYABLE,NULL))==NULL)
  170.   {
  171.    FreeAmigaBitMap (TempBitMap);
  172.    CloseFFR (FH);
  173.  
  174.    MySetIoErr (ERROR_NO_FREE_STORE);
  175.    return FALSE;
  176.   }
  177.  
  178.  BMHD->bmh_Width=Width;
  179.  BMHD->bmh_Height=Height;
  180.  BMHD->bmh_Depth=1;
  181.  for (Y=0L; Y<Height; Y++)
  182.   {
  183.    (void)memset(TempBitMap->Planes[0],'\0',TempBitMap->BytesPerRow);
  184.    for (X=0L, Mask=0; X<Width; X++, Mask>>=1)
  185.     {
  186.      if (Mask==0) Mask=128;
  187.  
  188.      if ((In=GetNum(FH))<0L)
  189.       {
  190.        FreeBitMap (BitMap);
  191.        FreeAmigaBitMap (TempBitMap);
  192.        CloseFFR (FH);
  193.  
  194.        MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  195.        return FALSE;
  196.       }
  197.      if (In>0L) TempBitMap->Planes[0][X>>3]|=Mask;
  198.     }
  199.    (void)BltBitMap(TempBitMap,0,0,BitMap,0,Y,Width,1,0xC0,0xFFFFFFFFL,NULL);
  200.   }
  201.  
  202.  FreeAmigaBitMap (TempBitMap);
  203.  CloseFFR (FH);
  204.  
  205.  ViewModes=BestModeID(BIDTAG_NominalWidth,Width,
  206.                       BIDTAG_NominalHeight,Height,
  207.                       BIDTAG_DesiredWidth,Width,
  208.                       BIDTAG_DesiredHeight,Height,
  209.                       BIDTAG_Depth,1L,
  210.                       TAG_DONE);
  211.  
  212.  (void)SetDTAttrs(O,NULL,NULL,
  213.                   DTA_ObjName,GetTagData(DTA_Name,NULL,Attrs),
  214.                   DTA_NominalHoriz,BMHD->bmh_Width,
  215.                   DTA_NominalVert,BMHD->bmh_Height,
  216.                   PDTA_BitMap,BitMap,
  217.                   PDTA_ModeID,ViewModes,
  218.                   TAG_DONE);
  219.  
  220.  return TRUE;
  221. }
  222.  
  223. /*
  224.  
  225.     Read P2/P3 format
  226.  
  227.     We use the new V43 interface to handle it.
  228.  
  229. */
  230.  
  231. LONG __regargs ReadPBMASC(struct FFRHandle *FH,struct BitMapHeader *BMHD,
  232.                           Class *C,Object *O,struct TagItem *Attrs,
  233.                           ULONG RectFmt)
  234.  
  235. {
  236.  LONG Width,Height,MaxVal,BytesPerPixel,BytesPerRow,Y,X,In;
  237.  UBYTE *Buffer,*Target;
  238.  
  239.  if ((Width=GetNum(FH))<1L)
  240.   {
  241.    CloseFFR (FH);
  242.  
  243.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  244.    return FALSE;
  245.   }
  246.  if ((Height=GetNum(FH))<1L)
  247.   {
  248.    CloseFFR (FH);
  249.  
  250.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  251.    return FALSE;
  252.   }
  253.  if ((MaxVal=GetNum(FH))<1L)
  254.   {
  255.    CloseFFR (FH);
  256.  
  257.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  258.    return FALSE;
  259.   }
  260.  
  261. /*
  262.  
  263.     We open picture.datatype" V43 so we can be sure do have the new
  264.     beast. If you want to support V39, too, you should better do some
  265.     checks at this point before trying to use the new features.
  266.  
  267. */
  268.  
  269. /*    Set witdh and height as usual. */
  270.  BMHD->bmh_Width=Width;
  271.  BMHD->bmh_Height=Height;
  272.  
  273. /*
  274.  
  275.     P2 format
  276.  
  277.     input:    grayscaled data
  278.     output:    8Bit chunky data, 1 byte per pixel
  279.  
  280. */
  281.  if (RectFmt==RECTFMT_LUT8)
  282.   {
  283.    struct ColorRegister *CMAP;
  284.    LONG Level,Number,*CRegs;
  285.    ULONG Index;
  286.  
  287. /*    Set depth and let "picture.dataype" allocate bitmap. */
  288.  
  289.    BMHD->bmh_Depth=8;
  290.    Level=0L;
  291.    Number=0L;
  292.    SetDTAttrs (O,NULL,NULL,
  293.                DTA_ObjName,GetTagData(DTA_Name,NULL,Attrs),
  294.                DTA_NominalHoriz,BMHD->bmh_Width,
  295.                DTA_NominalVert,BMHD->bmh_Height,
  296.                PDTA_SourceMode,MODE_V43,
  297.                PDTA_ModeID,0L,
  298.                DTA_ErrorLevel,&Level,
  299.                DTA_ErrorNumber,&Number,
  300.                TAG_DONE);
  301.  
  302. /*    Check if allocation was succesful. */
  303.    if (Level)
  304.     {
  305.      CloseFFR (FH);
  306.  
  307.      MySetIoErr (Number);
  308.      return FALSE;
  309.     }
  310.  
  311. /*    Create grayscale color palette. */
  312.    (void)SetDTAttrs(O,NULL,NULL,PDTA_NumColors,GRAYSCALE_COLORS,TAG_DONE);
  313.    if (GetDTAttrs(O,PDTA_ColorRegisters,&CMAP,PDTA_CRegs,&CRegs,TAG_DONE)==2L)
  314.     for (Index=0L; Index<GRAYSCALE_COLORS; Index++)
  315.      {
  316.       CMAP->red=Index;
  317.       CMAP->green=Index;
  318.       CMAP->blue=Index;
  319.       CMAP++;
  320.  
  321.       *CRegs++=RGB8to32(Index);
  322.       *CRegs++=RGB8to32(Index);
  323.       *CRegs++=RGB8to32(Index);
  324.      }
  325.   }
  326. /*
  327.  
  328.     P3 format
  329.  
  330.     input:    truecoloer RGB data
  331.     output:    24Bit RGB chunky data, 3 bytes per pixel
  332.  
  333. */
  334.  else
  335.   {
  336.    LONG Level,Number;
  337.  
  338. /*    Set depth and let "picture.dataype" allocate bitmap. */
  339.  
  340.    BMHD->bmh_Depth=24;
  341.    Level=0L;
  342.    Number=0L;
  343.    SetDTAttrs (O,NULL,NULL,
  344.                DTA_ObjName,GetTagData(DTA_Name,NULL,Attrs),
  345.                DTA_NominalHoriz,BMHD->bmh_Width,
  346.                DTA_NominalVert,BMHD->bmh_Height,
  347.                PDTA_SourceMode,MODE_V43,
  348.                PDTA_ModeID,0L,
  349.                DTA_ErrorLevel,&Level,
  350.                DTA_ErrorNumber,&Number,
  351.                TAG_DONE);
  352.  
  353. /*    Check if allocation was succesful. */
  354.    if (Level)
  355.     {
  356.      CloseFFR (FH);
  357.  
  358.      MySetIoErr (Number);
  359.      return FALSE;
  360.     }
  361.   }
  362.  
  363. /*    Allocated memory for input data. */
  364.  BytesPerPixel=BMHD->bmh_Depth>>3;
  365.  BytesPerRow=Width*BytesPerPixel;
  366.  if ((Buffer=AllocVec(BytesPerRow,MEMF_PUBLIC))==NULL)
  367.   {
  368.    CloseFFR (FH);
  369.  
  370.    MySetIoErr (ERROR_NO_FREE_STORE);
  371.    return FALSE;
  372.   }
  373.  
  374. /*    Read image data line by line. */
  375.  for (Y=0L; Y<Height; Y++)
  376.   {
  377.    Target=Buffer;
  378.    for (X=0L; X<BytesPerRow; X++)
  379.     if ((In=GetNum(FH))<0L)
  380.      {
  381.       FreeVec (Buffer);
  382.       CloseFFR (FH);
  383.  
  384.       MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  385.       return FALSE;
  386.      }
  387.     else *Target++=(UBYTE)(((In<<8)-In)/MaxVal);
  388.  
  389. /*    Copy image data to target bitmap. */
  390.    (void)DoSuperMethod(C,O,
  391.                        DTM_WRITEPIXELARRAY,Buffer,RectFmt,
  392.                        BytesPerRow,0,Y,Width,1L);
  393.   }
  394.  
  395.  FreeVec (Buffer);
  396.  CloseFFR (FH);
  397.  
  398.  return TRUE;
  399. }
  400.  
  401. /*
  402.  
  403.     P2 format: grayscale
  404.  
  405. */
  406.  
  407. LONG __regargs ReadPBM2(struct FFRHandle *FH,struct BitMapHeader *BMHD,
  408.                         Class *C,Object *O,struct TagItem *Attrs)
  409.  
  410. {
  411.  return ReadPBMASC(FH,BMHD,C,O,Attrs,RECTFMT_LUT8);
  412. }
  413.  
  414. /*
  415.  
  416.     P3 format: RGB truecolor
  417.  
  418. */
  419.  
  420. LONG __regargs ReadPBM3(struct FFRHandle *FH,struct BitMapHeader *BMHD,
  421.                        Class *C,Object *O,struct TagItem *Attrs)
  422.  
  423. {
  424.  return ReadPBMASC(FH,BMHD,C,O,Attrs,RECTFMT_RGB);
  425. }
  426.  
  427. /*
  428.  
  429.     P4 format: monochrom, binary
  430.  
  431.     We use the old pre V43 interface to handle it.
  432.  
  433. */
  434.  
  435. LONG __regargs ReadPBM4(struct FFRHandle *FH,struct BitMapHeader *BMHD,
  436.                         Class *C,Object *O,struct TagItem *Attrs)
  437.  
  438. {
  439.  LONG Width,Height,BytesPerRow,Y,*CRegs;
  440.  struct BitMap *TempBitMap,*BitMap;
  441.  struct ColorRegister *CMAP;
  442.  ULONG ViewModes;
  443.  
  444.  if ((Width=GetNum(FH))<1L)
  445.   {
  446.    CloseFFR (FH);
  447.  
  448.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  449.    return FALSE;
  450.   }
  451.  if ((Height=GetNum(FH))<1L)
  452.   {
  453.    CloseFFR (FH);
  454.  
  455.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  456.    return FALSE;
  457.   }
  458.  
  459.  (void)SetDTAttrs(O,NULL,NULL,PDTA_NumColors,2L,TAG_DONE);
  460.  if (GetDTAttrs(O,PDTA_ColorRegisters,&CMAP,PDTA_CRegs,&CRegs,TAG_DONE)==2L)
  461.   {
  462.    CMAP->red=255;
  463.    CMAP->green=255;
  464.    CMAP->blue=255;
  465.    CMAP++;
  466.  
  467.    *CRegs++=0xFFFFFFFFL;
  468.    *CRegs++=0xFFFFFFFFL;
  469.    *CRegs++=0xFFFFFFFFL;
  470.  
  471.    CMAP->red=0;
  472.    CMAP->green=0;
  473.    CMAP->blue=0;
  474.    CMAP++;
  475.  
  476.    *CRegs++=0x00000000L;
  477.    *CRegs++=0x00000000L;
  478.    *CRegs=0x00000000L;
  479.   }
  480.  
  481.  if ((TempBitMap=AllocAmigaBitMap(Width,1L))==NULL)
  482.   {
  483.    CloseFFR (FH);
  484.  
  485.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  486.    return FALSE;
  487.   }
  488.  
  489.  if ((BitMap=AllocBitMap(Width,Height,1L,BMF_CLEAR|BMF_DISPLAYABLE,NULL))==NULL)
  490.   {
  491.    FreeAmigaBitMap (TempBitMap);
  492.    CloseFFR (FH);
  493.  
  494.    MySetIoErr (ERROR_NO_FREE_STORE);
  495.    return FALSE;
  496.   }
  497.  
  498.  BMHD->bmh_Width=Width;
  499.  BMHD->bmh_Height=Height;
  500.  BMHD->bmh_Depth=1;
  501.  BytesPerRow=(Width+7L)>>3;
  502.  for (Y=0L; Y<Height; Y++)
  503.   if (READ(FH,TempBitMap->Planes[0],BytesPerRow))
  504.    {
  505.     FreeBitMap (BitMap);
  506.     FreeAmigaBitMap (TempBitMap);
  507.     CloseFFR (FH);
  508.  
  509.     MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  510.     return FALSE;
  511.    }
  512.   else (void)BltBitMap(TempBitMap,0,0,BitMap,0,Y,Width,1,0xC0,0xFFFFFFFFL,NULL);
  513.  
  514.  FreeAmigaBitMap (TempBitMap);
  515.  CloseFFR (FH);
  516.  
  517.  ViewModes=BestModeID(BIDTAG_NominalWidth,Width,
  518.                       BIDTAG_NominalHeight,Height,
  519.                       BIDTAG_DesiredWidth,Width,
  520.                       BIDTAG_DesiredHeight,Height,
  521.                       BIDTAG_Depth,1L,
  522.                       TAG_DONE);
  523.  
  524.  (void)SetDTAttrs(O,NULL,NULL,
  525.                   DTA_ObjName,GetTagData(DTA_Name,NULL,Attrs),
  526.                   DTA_NominalHoriz,BMHD->bmh_Width,
  527.                   DTA_NominalVert,BMHD->bmh_Height,
  528.                   PDTA_BitMap,BitMap,
  529.                   PDTA_ModeID,ViewModes,
  530.                   TAG_DONE);
  531.  
  532.  return TRUE;
  533. }
  534.  
  535. /*
  536.  
  537.     Read P2/P3 format
  538.  
  539.     We use the new V43 interface to handle it. Look at ReadPBMASC()
  540.     for a detailed description of the new interface.
  541.  
  542. */
  543.  
  544. LONG __regargs ReadPBMRaw(struct FFRHandle *FH,struct BitMapHeader *BMHD,
  545.                           Class *C,Object *O,struct TagItem *Attrs,
  546.                           ULONG RectFmt)
  547.  
  548. {
  549.  LONG Width,Height,MaxVal,BytesPerPixel,BytesPerRow,Y;
  550.  UBYTE *Buffer,*Target,Data;
  551.  ULONG Bytes;
  552.  
  553.  if ((Width=GetNum(FH))<1L)
  554.   {
  555.    CloseFFR (FH);
  556.  
  557.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  558.    return FALSE;
  559.   }
  560.  if ((Height=GetNum(FH))<1L)
  561.   {
  562.    CloseFFR (FH);
  563.  
  564.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  565.    return FALSE;
  566.   }
  567.  MaxVal=GetNum(FH);
  568.  if ((MaxVal<1L)||(MaxVal>255L))
  569.   {
  570.    CloseFFR (FH);
  571.  
  572.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  573.    return FALSE;
  574.   }
  575.  
  576.  BMHD->bmh_Width=Width;
  577.  BMHD->bmh_Height=Height;
  578.  if (RectFmt==RECTFMT_LUT8)
  579.   {
  580.    struct ColorRegister *CMAP;
  581.    LONG Level,Number,*CRegs;
  582.    ULONG Index;
  583.  
  584.    BMHD->bmh_Depth=8;
  585.    Level=0L;
  586.    Number=0L;
  587.    SetDTAttrs (O,NULL,NULL,
  588.                DTA_ObjName,GetTagData(DTA_Name,NULL,Attrs),
  589.                DTA_NominalHoriz,BMHD->bmh_Width,
  590.                DTA_NominalVert,BMHD->bmh_Height,
  591.                PDTA_SourceMode,MODE_V43,
  592.                PDTA_ModeID,0L,
  593.                DTA_ErrorLevel,&Level,
  594.                DTA_ErrorNumber,&Number,
  595.                TAG_DONE);
  596.  
  597.    if (Level)
  598.     {
  599.      CloseFFR (FH);
  600.  
  601.      MySetIoErr (Number);
  602.      return FALSE;
  603.     }
  604.  
  605.    (void)SetDTAttrs(O,NULL,NULL,PDTA_NumColors,GRAYSCALE_COLORS,TAG_DONE);
  606.    if (GetDTAttrs(O,PDTA_ColorRegisters,&CMAP,PDTA_CRegs,&CRegs,TAG_DONE)==2L)
  607.     for (Index=0L; Index<GRAYSCALE_COLORS; Index++)
  608.      {
  609.       CMAP->red=Index;
  610.       CMAP->green=Index;
  611.       CMAP->blue=Index;
  612.       CMAP++;
  613.  
  614.       *CRegs++=RGB8to32(Index);
  615.       *CRegs++=RGB8to32(Index);
  616.       *CRegs++=RGB8to32(Index);
  617.      }
  618.   }
  619.  else
  620.   {
  621.    LONG Level,Number;
  622.  
  623.    BMHD->bmh_Depth=24;
  624.    Level=0L;
  625.    Number=0L;
  626.    SetDTAttrs (O,NULL,NULL,
  627.                DTA_ObjName,GetTagData(DTA_Name,NULL,Attrs),
  628.                DTA_NominalHoriz,BMHD->bmh_Width,
  629.                DTA_NominalVert,BMHD->bmh_Height,
  630.                PDTA_SourceMode,MODE_V43,
  631.                PDTA_ModeID,0L,
  632.                DTA_ErrorLevel,&Level,
  633.                DTA_ErrorNumber,&Number,
  634.                TAG_DONE);
  635.  
  636.    if (Level)
  637.     {
  638.      CloseFFR (FH);
  639.  
  640.      MySetIoErr (Number);
  641.      return FALSE;
  642.     }
  643.   }
  644.  
  645.  BytesPerPixel=BMHD->bmh_Depth>>3;
  646.  BytesPerRow=Width*BytesPerPixel;
  647.  if ((Buffer=AllocVec(BytesPerRow,MEMF_PUBLIC))==NULL)
  648.   {
  649.    CloseFFR (FH);
  650.  
  651.    MySetIoErr (ERROR_NO_FREE_STORE);
  652.    return FALSE;
  653.   }
  654.  
  655.  for (Y=0L; Y<Height; Y++)
  656.   {
  657.    Target=Buffer;
  658.    if (READ(FH,Target,BytesPerRow))
  659.     {
  660.      FreeVec (Buffer);
  661.      CloseFFR (FH);
  662.  
  663.      MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  664.      return FALSE;
  665.     }
  666.  
  667.    if (MaxVal<255L)
  668.     {
  669.      Bytes=BytesPerRow;
  670.      while (Bytes--)
  671.       {
  672.        Data=*Target;
  673.        *Target++=((Data<<8)-Data)/MaxVal;
  674.       }
  675.     }
  676.  
  677.    (void)DoSuperMethod(C,O,
  678.                        DTM_WRITEPIXELARRAY,Buffer,RectFmt,
  679.                        BytesPerRow,0,Y,Width,1L);
  680.   }
  681.  
  682.  FreeVec (Buffer);
  683.  CloseFFR (FH);
  684.  
  685.  return TRUE;
  686. }
  687.  
  688. /*
  689.  
  690.     P5 format: grayscale, binary
  691.  
  692. */
  693.  
  694. LONG __regargs ReadPBM5(struct FFRHandle *FH,struct BitMapHeader *BMHD,
  695.                         Class *C,Object *O,struct TagItem *Attrs)
  696.  
  697. {
  698.  return ReadPBMRaw(FH,BMHD,C,O,Attrs,RECTFMT_LUT8);
  699. }
  700.  
  701. /*
  702.  
  703.     P6 format: RGB truecolor, binary
  704.  
  705. */
  706.  
  707. LONG __regargs ReadPBM6(struct FFRHandle *FH,struct BitMapHeader *BMHD,
  708.                        Class *C,Object *O,struct TagItem *Attrs)
  709.  
  710. {
  711.  return ReadPBMRaw(FH,BMHD,C,O,Attrs,RECTFMT_RGB);
  712. }
  713.  
  714. LONG __regargs ReadPBM(Class *C,Object *O,struct TagItem *Attrs)
  715.  
  716. {
  717.  ULONG SourceType;
  718.  BPTR Handle;
  719.  struct BitMapHeader *BMHD;
  720.  char PBMHeader[PBM_HEADER_SIZE];
  721.  LONG __regargs (*ReadFunc)(struct FFRHandle *,struct BitMapHeader *,
  722.                             Class *,Object *,struct TagItem *);
  723.  struct FFRHandle *FH;
  724.  
  725.  SourceType=0L;
  726.  Handle=NULL;
  727.  BMHD=NULL;
  728.  if (GetDTAttrs(O,
  729.                 DTA_SourceType,&SourceType,
  730.                 DTA_Handle,&Handle,
  731.                 PDTA_BitMapHeader,&BMHD,
  732.                 TAG_DONE)!=3L)
  733.   {
  734.    MySetIoErr (ERROR_OBJECT_NOT_FOUND);
  735.    return FALSE;
  736.   }
  737.  if ((SourceType!=DTST_FILE)||(Handle==NULL)||(BMHD==NULL))
  738.   {
  739.    MySetIoErr (ERROR_OBJECT_NOT_FOUND);
  740.    return FALSE;
  741.   }
  742.  
  743.  (void)Seek(Handle,0L,OFFSET_BEGINNING);
  744.  if (Read(Handle,PBMHeader,PBM_HEADER_SIZE)!=PBM_HEADER_SIZE)
  745.   {
  746.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  747.    return FALSE;
  748.   }
  749.  
  750.  if ((PBMHeader[0]!='P')||!IsWhiteSpace(PBMHeader[2]))
  751.   {
  752.    MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  753.    return FALSE;
  754.   }
  755.  
  756.  switch (PBMHeader[1])
  757.   {
  758.    case '1':
  759.     ReadFunc=ReadPBM1;
  760.     break;
  761.    case '2':
  762.     ReadFunc=ReadPBM2;
  763.     break;
  764.    case '3':
  765.     ReadFunc=ReadPBM3;
  766.     break;
  767.    case '4':
  768.     ReadFunc=ReadPBM4;
  769.     break;
  770.    case '5':
  771.     ReadFunc=ReadPBM5;
  772.     break;
  773.    case '6':
  774.     ReadFunc=ReadPBM6;
  775.     break;
  776.    default:
  777.     MySetIoErr (ERROR_OBJECT_WRONG_TYPE);
  778.     return FALSE;
  779.   }
  780.  
  781.  if ((FH=OpenFFR(Handle,PBM_HEADER_SIZE))==NULL)
  782.   {
  783.    MySetIoErr (ERROR_NO_FREE_STORE);
  784.    return FALSE;
  785.   }
  786.  
  787.  return ReadFunc(FH,BMHD,C,O,Attrs);
  788. }
  789.